﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace HanoiTowerWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var task = Task.Run(() =>
            {
                double speedx = 2.4;
                double speedy = 10;
                while (true)
                {
                    this.Dispatcher.Invoke(() =>
                    {
                        var left = Canvas.GetLeft(rect);
                        var top = Canvas.GetTop(rect);

                        if (left < 0)
                        {
                            left = 0;
                            speedx = -speedx;
                        }
                        else if (left + rect.ActualWidth >= canvas.ActualWidth)
                        {
                            left = canvas.ActualWidth - rect.ActualWidth - 1;
                            speedx = -speedx;
                        }


                        if (top < 0 || top + rect.ActualHeight >= canvas.ActualHeight)
                            speedy = -speedy;


                        left += speedx;
                        top += speedy;

                        Canvas.SetLeft(rect, left);
                        Canvas.SetTop(rect, top);
                    });


                    Thread.Sleep(10);
                }
            });
        }

        private void btnAnimate_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation daX = new DoubleAnimation();
            DoubleAnimation daY = new DoubleAnimation();
            //指定起点
            daX.From = 30;
            daY.From = 30;

            //指定终点
            Random r = new Random();
            daX.To = r.NextDouble() * 300;
            daY.To = r.NextDouble() * 300;

            //指定时长
            Duration duration = new Duration(TimeSpan.FromMilliseconds(300));
            daX.Duration = duration;
            daY.Duration = duration;

            //动画的主题是TranslateTransform变形，而非Button
            this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, daY);
        }

        private void btn1_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimationUsingKeyFrames dakX = new DoubleAnimationUsingKeyFrames();
            DoubleAnimationUsingKeyFrames dakY = new DoubleAnimationUsingKeyFrames();
            // 设置动画总时长
            dakX.Duration = new Duration(TimeSpan.FromMilliseconds(900));
            dakY.Duration = new Duration(TimeSpan.FromMilliseconds(900));
            // 创建关键帧
            LinearDoubleKeyFrame x_kf_1 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame x_kf_2 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame x_kf_3 = new LinearDoubleKeyFrame();
            //设置关键帧
            x_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300));
            x_kf_1.Value = 200;
            x_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600));
            x_kf_2.Value = 0;
            x_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900));
            x_kf_3.Value = 200;
            //添加关键帧
            dakX.KeyFrames.Add(x_kf_1);
            dakX.KeyFrames.Add(x_kf_2);
            dakX.KeyFrames.Add(x_kf_3);

            LinearDoubleKeyFrame y_kf_1 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame y_kf_2 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame y_kf_3 = new LinearDoubleKeyFrame();
            y_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300));
            y_kf_1.Value = 0;
            y_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600));
            y_kf_2.Value = 180;
            y_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900));
            y_kf_3.Value = 180;
            dakY.KeyFrames.Add(y_kf_1);
            dakY.KeyFrames.Add(y_kf_2);
            dakY.KeyFrames.Add(y_kf_3);

            //执行动画
            this.tt.BeginAnimation(TranslateTransform.XProperty, dakX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, dakY);
        }

        private Storyboard myStoryboard;
        private void btn3_Click(object sender, RoutedEventArgs e)
        {
            //StackPanel myPanel = new StackPanel();
            //myPanel.Margin = new Thickness(10);

            Rectangle myRectangle = new Rectangle();
            myRectangle.Name = "myRectangle";
            this.RegisterName(myRectangle.Name, myRectangle);
            myRectangle.Width = 100;
            myRectangle.Height = 200;
            myRectangle.Fill = Brushes.Blue;

            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 1.0;
            myDoubleAnimation.To = 0.0;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
            myDoubleAnimation.AutoReverse = true;
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            myStoryboard = new Storyboard();
            myStoryboard.Children.Add(myDoubleAnimation);
            Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
            Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));

            // Use the Loaded event to start the Storyboard.
            myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);
            canvas.Children.Add(myRectangle);
            //myPanel.Children.Add(myRectangle);
            //this.Content = myPanel;
        }

        private void myRectangleLoaded(object sender, RoutedEventArgs e)
        {
            myStoryboard.Begin(this);
        }

        public void MatrixAnimationUsingPathDoesRotateWithTangentExample(Shape shape)
        {
            // Create a NameScope for the page so that we can use Storyboards.
            NameScope.SetNameScope(this, new NameScope());

            // Create a MatrixTransform. This transform  will be used to move the button.
            MatrixTransform buttonMatrixTransform = new MatrixTransform();
            shape.RenderTransform = buttonMatrixTransform;

            // Register the transform's name with the page so that it can be targeted by a Storyboard.
            this.RegisterName("ButtonMatrixTransform", buttonMatrixTransform);



            // Create the animation path.
            PathGeometry animationPath = new PathGeometry();
            double x = Canvas.GetLeft(shape);
            double y = Canvas.GetTop(shape);

            PathFigure pFigure = new PathFigure() { StartPoint = new Point(x, y) };
            pFigure.Segments.Add(new BezierSegment()
            {
                Point1 = new Point(x, y),
                Point2 = new Point(x + 100, y - 100),
                Point3 = new Point(x + 200, y)
            });

            animationPath.Figures.Add(pFigure);

            // Freeze the PathGeometry for performance benefits.
            animationPath.Freeze();

            // Create a MatrixAnimationUsingPath to move the button along the path by animating its MatrixTransform.
            MatrixAnimationUsingPath matrixAnimation = new MatrixAnimationUsingPath();
            matrixAnimation.AccelerationRatio = 0.2;

            matrixAnimation.PathGeometry = animationPath;
            matrixAnimation.Duration = TimeSpan.FromSeconds(0.4);
            // matrixAnimation.RepeatBehavior = RepeatBehavior.Forever;

            // Set the animation's DoesRotateWithTangent property to true so that rotates the rectangle in addition to moving it.
            // matrixAnimation.DoesRotateWithTangent = true; // 矩型跟着路径倾斜

            // Set the animation to target the Matrix property of the MatrixTransform named "ButtonMatrixTransform".
            Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform");
            Storyboard.SetTargetProperty(matrixAnimation, new PropertyPath(MatrixTransform.MatrixProperty));

            // Create a Storyboard to contain and apply the animation.
            Storyboard pathAnimationStoryboard = new Storyboard();
            pathAnimationStoryboard.Children.Add(matrixAnimation);

            // Start the storyboard when the button is loaded. 貌似可以不要。
            //rect1.Loaded += delegate (object sender, RoutedEventArgs e)
            //{
            //    pathAnimationStoryboard.Begin(this);
            //};

            // 由于是通过变换得到的新坐标，所以变化的是变换，而不是直接的坐标。如何解决，待定。
            pathAnimationStoryboard.Completed += (s, e) =>
            {
                Debug.WriteLine($"original:{x}, current:{Canvas.GetLeft(shape)}");
                Canvas.SetLeft(shape, x + 100);
                Canvas.SetTop(shape,y);
                shape.RenderTransform = new MatrixTransform();
            };


            pathAnimationStoryboard.Begin(canvas);
        }

      

        private void btn4_Click(object sender, RoutedEventArgs e)
        {
            MatrixAnimationUsingPathDoesRotateWithTangentExample(rect1);
        }

        private void btn5_Click(object sender, RoutedEventArgs e)
        {
            var canvas = (Canvas)this.Content;
            Console.WriteLine(canvas.Children[0]);
        }
    }
}
